namespace OpenComposite.EII.Repository
{
	using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Data;
	using System.Drawing;
	using System.IO;
	using System.Text;
	using System.Windows.Forms;
	using System.Xml;
	using System.Xml.Schema;

	using OpenComposite.EII.Services;

	using OpenComposite.Base;
	using OpenComposite.Base.Collections;
	using OpenComposite.Repository.Properties;

	// Not obsolete yet!
	//[Obsolete]
	[RepositoryItem(ItemType.Operation, "operations", "operation_id")]
	[DesignerAttribute(typeof(OperationDesigner))]
	[TypeConverter(typeof(ExpandableObjectConverter))]
	public class Operation : RepositoryItemBaseEx
	{
		#region Initialization

		/// <summary>
		/// Initializes a new instance of the <see cref="Operation"/> class.
		/// </summary>
		public Operation()
			: base("operation_id", "operation_nm", "operation_desc", "operation_ntext", Resources.sNewOperation)
		{
			_input_xsd = null;
			_output_xsd = null;
			_input_formstyle = null;
			_output_formstyle = null;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Operation"/> class.
		/// </summary>
		/// <param name="bCreateNew">if set to <c>true</c> [b create new].</param>
		public Operation(bool bCreateNew)
			: this()
		{
			if ( bCreateNew )
				this.CreateNew();
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Operation"/> class.
		/// </summary>
		/// <param name="id">The id.</param>
		public Operation(int id)
			: this()
		{
			this.Load(id);
		}

		#endregion Initialization

		#region Public Members

		#region Properties

		/// <summary>
		/// Gets the allowed child types.
		/// </summary>
		/// <value>The allowed child types.</value>
		public override List<ItemType> AllowedChildTypes
		{
			get { return _LISTALLOWED; }
		}

		/// <summary>
		/// Gets or sets the composed verb.
		/// </summary>
		/// <value>The composed verb.</value>
		public Verb ComposedVerb
		{
			get
			{
				if ( this.ComposedVerbID > 0 ) {
					return this.RepositoryService.GetItem<Verb>(this.ComposedVerbID);
				} else {
					return null;
				}
			}
			set
			{
				if ( value != null ) {
					this.ComposedVerbID = value.ID;
				} else {
					this.ComposedVerbID = -1;
				}
			}
		}

		/// <summary>
		/// Gets or sets the composed verb ID.
		/// </summary>
		/// <value>The composed verb ID.</value>
		public int ComposedVerbID
		{
			get { return getInt("operation_verb_id", -1); }
			set { setValue("ComposedVerbID", "operation_verb_id", (object)value); }
		}

		/// <summary>
		/// Gets or sets the exposed service module.
		/// </summary>
		/// <value>The exposed service module.</value>
		public ServiceModule ExposedServiceModule
		{
			get
			{
				if ( this.ExposedServiceModuleID > 0 ) {
					return this.RepositoryService.GetItem<ServiceModule>(this.ExposedServiceModuleID);
				} else {
					return null;
				}
			}
			set
			{
				if ( value != null ) {
					this.ExposedServiceModuleID = value.ID;
				} else {
					this.ExposedServiceModuleID = -1;
				}
			}
		}

		/// <summary>
		/// Gets or sets the exposed service module ID.
		/// </summary>
		/// <value>The exposed service module ID.</value>
		public int ExposedServiceModuleID
		{
			get { return getInt("exposed_svcmodule_id", -1); }
			set { setValue("ExposedServiceModuleID", "exposed_svcmodule_id", value); }
		}

		/// <summary>
		/// Gets or sets the exposed verb.
		/// </summary>
		/// <value>The exposed verb.</value>
		public Verb ExposedVerb
		{
			get
			{
				if ( this.ExposedVerbID > 0 ) {
					return this.RepositoryService.GetItem<Verb>(this.ExposedVerbID);
				} else {
					return null;
				}
			}
			set
			{
				if ( value != null ) {
					//if ( this.ExposedVerb != value ) {
					//    this.ExposedVerb.ItemChanged -= ExposedVerb_ItemChanged;
					//    value.ItemChanged += new RepositoryChangedEventHandler(ExposedVerb_ItemChanged);
					//}
					this.ExposedVerbID = value.ID;
				} else {
					this.ExposedVerbID = -1;
				}
			}
		}

		/// <summary>
		/// Gets or sets the exposed verb ID.
		/// </summary>
		/// <value>The exposed verb ID.</value>
		public int ExposedVerbID
		{
			get { return getInt("exposed_verb_id", -1); }
			set { setValue("ExposedVerbID", "exposed_verb_id", value); }
		}

		/// <summary>
		/// Gets or sets the exposed workflow.
		/// </summary>
		/// <value>The exposed workflow.</value>
		public Workflow ExposedWorkflow
		{
			get { return this.RepositoryService.GetItem<Workflow>(ExposedWorkflowId); }
			set { ExposedWorkflowId = value == null ? -1 : value.ID; }
		}

		/// <summary>
		/// Gets or sets the exposed workflow id.
		/// </summary>
		/// <value>The exposed workflow id.</value>
		public int ExposedWorkflowId
		{
			get { return getInt("operation_exposed_workflow_id", -1); }
			set { setValue("ExposedWorkflowId", "operation_exposed_workflow_id", value); }
		}

		/// <summary>
		/// Gets the image.
		/// </summary>
		/// <value>The image.</value>
		public override Image Image
		{
			get { return Resources.method; }
		}

		/// <summary>
		/// Gets the image key.
		/// </summary>
		/// <value>The image key.</value>
		public override string ImageKey
		{
			get { return "method"; }
		}

		/// <summary>
		/// Gets or sets the input business object id.
		/// </summary>
		/// <value>The input business object id.</value>
		public int InputBusinessObjectId
		{
			get
			{
				if ( this.ExposedVerbID > 0 ) {
					return this.ExposedVerb.InputBusinessObjectID;
				} else {
					return getInt("operation_input_bobj_id", -1);
				}
			}
			set { setValue("InputBusinessObjectId", "operation_input_bobj_id", value); }
		}

		/// <summary>
		/// Gets or sets the name of the input business object.
		/// </summary>
		/// <value>The name of the input business object.</value>
		public string InputBusinessObjectName
		{
			get
			{
				if ( this.InputBusinessObjectId > 0 ) {
					BusinessObject bo = this.GetInputBusinessObject();
					if ( bo != null ) return bo.Name; else return null;
				} else {
					return null;
				}
			}
			set { setValue("InputBusinessObjectName", "operation_input_bobj_nm", value); }
		}

		/// <summary>
		/// Gets or sets the input form style.
		/// </summary>
		/// <value>The input form style.</value>
		public XmlDocument InputFormStyle
		{
			get
			{
				if ( _input_formstyle == null )
					_input_formstyle = getXmlDocument("operation_input_formstyle");
				return _input_formstyle;
			}
			set
			{
				_input_formstyle = value;
				setXmlDocument("InputFormStyle", "operation_input_formstyle", _input_formstyle);
			}
		}

		/// <summary>
		/// Gets or sets the input schema.
		/// </summary>
		/// <value>The input schema.</value>
		public XmlSchema InputSchema
		{
			get
			{
				if ( this.InputBusinessObjectId > 0 ) {
					BusinessObject bo = this.RepositoryService.GetItem<BusinessObject>(this.InputBusinessObjectId);
					_input_xsd = bo.Schema;
				} else {
					_input_xsd = getSchema("operation_input_schema");
				}
				return _input_xsd;
			}
			set
			{
				_input_xsd = value;
				setSchema("InputSchema", "operation_input_schema", _input_xsd);
			}
		}

		/// <summary>
		/// Gets the input schema string.
		/// </summary>
		/// <value>The input schema string.</value>
		public string InputSchemaString
		{
			get
			{
				if ( this.InputBusinessObjectId > 0 ) {
					BusinessObject bo = this.RepositoryService.GetItem<BusinessObject>(this.InputBusinessObjectId);
					return bo.SchemaString;
				} else
					return getString("operation_input_schema", null);
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is input business object schema.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is input business object schema; otherwise, <c>false</c>.
		/// </value>
		public bool IsInputBusinessObjectSchema
		{
			get { return getBool("operation_input_isbobjxsd", false); }
			set { setValue("IsInputBusinessObjectSchema", "operation_input_isbobjxsd", value); }
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is output business object schema.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is output business object schema; otherwise, <c>false</c>.
		/// </value>
		public bool IsOutputBusinessObjectSchema
		{
			get { return getBool("operation_output_isbobjxsd", false); }
			set { setValue("IsOutputBusinessObjectSchema", "operation_output_isbobjxsd", value); }
		}

		/// <summary>
		/// Gets or sets the name.
		/// </summary>
		/// <value>The name.</value>
		public override string Name
		{
			get
			{
				if ( this.ExposedVerb != null ) {
					return this.ExposedVerb.Name;
				} else {
					return base.Name;
				}
			}
			set
			{
				if ( this.ExposedVerb != null ) {
					this.ExposedVerb.Name = value;
				} else {
					base.Name = value;
				}
			}
		}

		/// <summary>
		/// Gets or sets the output business object id.
		/// </summary>
		/// <value>The output business object id.</value>
		public int OutputBusinessObjectId
		{
			get
			{
				if ( this.ExposedVerbID > 0 ) {
					return this.ExposedVerb.OutputBusinessObjectID;
				} else {
					return getInt("operation_output_bobj_id", -1);
				}
			}
			set { setValue("OutputBusinessObjectId", "operation_output_bobj_id", value); }
		}

		/// <summary>
		/// Gets or sets the name of the output business object.
		/// </summary>
		/// <value>The name of the output business object.</value>
		public string OutputBusinessObjectName
		{
			get
			{
				if ( this.OutputBusinessObjectId > 0 ) {
					BusinessObject bo = this.GetOutputBusinessObject();
					if ( bo != null ) return bo.Name; else return null;
				} else {
					return null;
				}
			}
			set { setValue("OutputBusinessObjectName", "operation_output_bobj_nm", value); }
		}

		/// <summary>
		/// Gets or sets the output form style.
		/// </summary>
		/// <value>The output form style.</value>
		public XmlDocument OutputFormStyle
		{
			get
			{
				if ( _output_formstyle == null )
					_output_formstyle = getXmlDocument("operation_output_formstyle");
				return _output_formstyle;
			}
			set
			{
				_output_formstyle = value;
				setXmlDocument("OutputFormStyle", "operation_output_formstyle", _output_formstyle);
			}
		}

		/// <summary>
		/// Gets or sets the output schema.
		/// </summary>
		/// <value>The output schema.</value>
		public XmlSchema OutputSchema
		{
			get
			{
				if ( this.OutputBusinessObjectId > 0 ) {
					BusinessObject bo = this.RepositoryService.GetItem<BusinessObject>(this.OutputBusinessObjectId);
					_output_xsd = bo.Schema;
				} else
					_output_xsd = getSchema("operation_output_schema");
				return _output_xsd;
			}
			set
			{
				_output_xsd = value;
				setSchema("OutputSchema", "operation_output_schema", _output_xsd);
			}
		}

		/// <summary>
		/// Gets the output schema string.
		/// </summary>
		/// <value>The output schema string.</value>
		public string OutputSchemaString
		{
			get
			{
				if ( this.OutputBusinessObjectId > 0 ) {
					BusinessObject bo = this.RepositoryService.GetItem<BusinessObject>(this.OutputBusinessObjectId);
					return bo.SchemaString;
				} else
					return getString("operation_output_schema", null);
			}
		}

		/// <summary>
		/// Gets or sets the process GUID.
		/// </summary>
		/// <value>The process GUID.</value>
		public Guid ProcessGuid
		{
			get { return Guid.Empty;/*getGuid("operation_bpel_guid", Guid.Empty);*/ }
			set
			{
				/*
				if ( value == Guid.Empty )
					setValue("ProcessGuid", "operation_bpel_guid", null);
				else
					setValue("ProcessGuid", "operation_bpel_guid", value);
				*/
			}
		}

		/// <summary>
		/// Gets the type of the repository item.
		/// </summary>
		/// <value>The type of the repository item.</value>
		public override ItemType RepositoryItemType
		{
			get { return ItemType.Operation; }
		}

		/// <summary>
		/// Gets the repository item type description.
		/// </summary>
		/// <value>The repository item type description.</value>
		public override string RepositoryItemTypeDescription
		{
			get { return ""; }
		}

		/// <summary>
		/// Gets the name of the repository item type.
		/// </summary>
		/// <value>The name of the repository item type.</value>
		public override string RepositoryItemTypeName
		{
			get { return Resources.sVerb/*sSvcMethod*/; }
		}

		/// <summary>
		/// Gets the selected image.
		/// </summary>
		/// <value>The selected image.</value>
		public override Image SelectedImage
		{
			get { return this.Image; }
		}

		/// <summary>
		/// Gets the selected image key.
		/// </summary>
		/// <value>The selected image key.</value>
		public override string SelectedImageKey
		{
			get { return "method"; }
		}

		/// <summary>
		/// Gets or sets the service module.
		/// </summary>
		/// <value>The service module.</value>
		public ServiceModule ServiceModule
		{
			get
			{
				if ( this.ServiceModuleID > 0 ) {
					return this.RepositoryService.GetItem<ServiceModule>(this.ServiceModuleID);
				} else {
					return null;
				}
			}
			set
			{
				if ( value != null ) {
					this.ServiceModuleID = value.ID;
				} else {
					this.ServiceModuleID = -1;
				}
			}
		}

		/// <summary>
		/// Gets or sets the service module ID.
		/// </summary>
		/// <value>The service module ID.</value>
		public int ServiceModuleID
		{
			get { return getInt("svcmodule_id", -1); }
			set { setValue("ServiceModuleID", "svcmodule_id", value); }
		}

		/// <summary>
		/// Gets the name of the table.
		/// </summary>
		/// <value>The name of the table.</value>
		public override string TableName
		{
			get { return "operations"; }
		}

		/// <summary>
		/// Gets or sets the workflow id.
		/// </summary>
		/// <value>The workflow id.</value>
		public int WorkflowId
		{
			get { return getInt("operation_workflow_id", -1); }
			set { setValue("WorkflowId", "operation_workflow_id", value); }
		}

		#endregion Properties

		#region Methods

		/// <summary>
		/// Assigns the logical activity.
		/// </summary>
		/// <param name="idLogicalActivity">The id logical activity.</param>
		/// <returns></returns>
		public LogicalActivity AssignLogicalActivity(int idLogicalActivity)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			bool bSC;
			LogicalActivity logact = null;
			if ( idLogicalActivity > 0 ) {
				logact = repSvc.GetItem(ItemType.LogicalActivity, idLogicalActivity, true) as LogicalActivity;
				if ( logact.OperationID != this.ID ) {
					logact.OperationID = this.ID;
				}
			} else {
				logact = repSvc.GetItem(ItemType.LogicalActivity, true,
					Global.Status.CurrentRepositoryId, false, false, out bSC) as LogicalActivity;
				logact.BeginEdit();
				try {
					logact.OperationID = this.ID;
					logact.Name = this.Name;
					logact.Description = this.Description;
					logact.NText = this.NText;
				} finally {
					logact.EndEdit(true);
				}
			}
			return logact;
		}

		/// <summary>
		/// Copies this instance.
		/// </summary>
		/// <param name="deep"><c>true</c> to recursively copy the item and all subitems;
		/// <c>false</c> to copy only the item itself.</param>
		/// <returns>The copied item.</returns>
		public override IRepositoryItem Copy(bool deep)
		{
			Operation copy = new Operation(true);
			copy.InitializeServiceProvider(this);
			this.CopyDataRowToTarget(copy);
			return copy;
		}

		/// <summary>
		/// Gets the icon.
		/// </summary>
		/// <returns></returns>
		public override Icon GetIcon()
		{
			Bitmap bmp = new Bitmap(this.Image);
			bmp.MakeTransparent(Color.Magenta);
			return Icon.FromHandle(bmp.GetHicon());
		}

		/// <summary>
		/// Gets the input business object.
		/// </summary>
		/// <returns></returns>
		public BusinessObject GetInputBusinessObject()
		{
			if ( this.InputBusinessObjectId > 0 )
				return this.RepositoryService.GetItem(ItemType.BObject, this.InputBusinessObjectId, false) as BusinessObject;
			else
				return null;
		}

		/// <summary>
		/// Gets the KPI metrics.
		/// </summary>
		/// <returns></returns>
		public BindingListEx<KPIMetric> GetKPIMetrics()
		{
			return Global.Data.GetRepositoryHierarchyChildRepositoryList<KPIMetric>(
					ItemType.Operation, this.ID, ItemType.KPI_Metric);
		}

		/// <summary>
		/// Gets the logical activities.
		/// </summary>
		/// <returns></returns>
		public BindingListEx<LogicalActivity> GetLogicalActivities()
		{
			return Global.Data.GetLogicalActivitiesByOperation(this.ID);
		}

		/// <summary>
		/// Gets the output business object.
		/// </summary>
		/// <returns></returns>
		public BusinessObject GetOutputBusinessObject()
		{
			if ( this.OutputBusinessObjectId > 0 )
				return this.RepositoryService.GetItem(ItemType.BObject, this.OutputBusinessObjectId, false) as BusinessObject;
			else
				return null;
		}

		/// <summary>
		/// Gets the service.
		/// </summary>
		/// <returns></returns>
		public Service GetService()
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			Service svc = null;
			DataTable dt = Global.Data.GetRepositoryParentsOfType
				(ItemType.Operation, this.ID, ItemType.GenericFolder);
			if ( dt != null && dt.Rows.Count > 0 ) {
				foreach ( DataRow dr in dt.Rows ) {
					GenericFolder gf = repSvc.GetItem(ItemType.GenericFolder, (int)dr["parent_id"], true) as GenericFolder;
					if ( gf == null || gf.Name != "Service" )
						continue;
					DataTable dt1 = Global.Data.GetRepositoryParentsOfType
						(ItemType.GenericFolder, (int)dr["parent_id"], ItemType.Component);
					if ( dt1 != null ) {
						foreach ( DataRow dr1 in dt1.Rows ) {
							svc = repSvc.GetItem(ItemType.Component, (int)dr1["parent_id"], true) as Service;
							if ( svc != null /*&& svc.Type == Service.ServiceType.Orchestration*/ )
								return svc;
							else
								svc = null;
						}
					}
				}
			}
			return svc;
		}

		/// <summary>
		/// Gets the workflow.
		/// </summary>
		/// <returns></returns>
		public Workflow GetWorkflow()
		{
			RepositoryService repSvc = GetService(typeof(RepositoryService)) as RepositoryService;
			if ( repSvc == null || this.WorkflowId <= 0 )
				return null;
			return repSvc.GetItem(ItemType.Workflow, this.WorkflowId, false) as Workflow;
		}

		/// <summary>
		/// Sets the input business object.
		/// </summary>
		/// <param name="bobject">The bobject.</param>
		public void SetInputBusinessObject(BusinessObject bobject)
		{
			if ( bobject != null ) {
				this.InputBusinessObjectId = bobject.ID;
				this.InputBusinessObjectName = bobject.Name;
				this.InputSchema = bobject.Schema;
			} else {
				this.InputBusinessObjectId = -1;
				this.InputBusinessObjectName = "";
				this.InputSchema = null;
			}
		}

		/// <summary>
		/// Sets the output business object.
		/// </summary>
		/// <param name="bobject">The bobject.</param>
		public void SetOutputBusinessObject(BusinessObject bobject)
		{
			if ( bobject != null ) {
				this.OutputBusinessObjectId = bobject.ID;
				this.OutputBusinessObjectName = bobject.Name;
				this.OutputSchema = bobject.Schema;
			} else {
				this.OutputBusinessObjectId = -1;
				this.OutputBusinessObjectName = "";
				this.OutputSchema = null;
			}
		}

		#endregion Methods

		#endregion Public Members

		#region Protected Members

		#region Methods

		/// <summary>
		/// Sets the default values.
		/// </summary>
		protected override void SetDefaultValues()
		{
			if ( row == null )
				return;
			this.BeginEdit();
			try {
				base.SetDefaultValues();

				setValue("IsInputBusinessObjectSchema", "operation_input_isbobjxsd", false);
				setValue("IsOutputBusinessObjectSchema", "operation_output_isbobjxsd", false);
			} finally {
				this.EndEdit(false);
			}
		}

		#endregion Methods

		#endregion Protected Members

		#region Private Members

		#region Static Fields

		private static List<ItemType> _LISTALLOWED = new List<ItemType>();

		#endregion Static Fields

		#region Fields

		private XmlDocument _input_formstyle;
		private XmlSchema _input_xsd;
		private XmlDocument _output_formstyle;
		private XmlSchema _output_xsd;

		#endregion Fields

		#region Event Handlers

		private void ExposedVerb_ItemChanged(object sender, RepositoryChangedEventArgs e)
		{
			if ( e.Member != null && e.Member.Name == "Name" && e.NewValue != null ) {
				this.Name = e.NewValue.ToString();
			}
		}

		#endregion Event Handlers

		#endregion Private Members
	}

	//[System.Security.Permissions.PermissionSet(
	//	System.Security.Permissions.SecurityAction.Demand,
	//	Name = "FullTrust")]
	internal class OperationDesigner : RepositoryItemDesigner
	{
		#region Public Members

		#region Methods

		/// <summary>
		/// Gets the type of the designer control item.
		/// </summary>
		/// <returns></returns>
		public override ItemType GetDesignerControlItemType()
		{
			Operation op = this.Component as Operation;
			if ( op == null ) return base.GetDesignerControlItemType();
			if ( op.ExposedVerbID > 0 ) {
				return ItemType.Verb;
			} else {
				return base.GetDesignerControlItemType();
			}
		}

		#endregion Methods

		#endregion Public Members
	}
}